﻿using System;
using System.ServiceModel;
using Less.Core;
using Less.Tools;

namespace Less.Web
{
    public static class Templates
    {
        // TODO: Check ActionTemplate with class parameters
        // TODO: Add entryCategory parameter to all template methods
        public static string GetUserName()
        {
            return ServiceSecurityContext.Current.PrimaryIdentity != null ? ServiceSecurityContext.Current.PrimaryIdentity.Name : "";
        }
        

        public static void ActionTemplate<T>(Action<T> workerMethod, T param, EntryCategories entryCategory)
        {
            if (workerMethod == null)
            {
                throw new ArgumentNullException("workerMethod");
            }
            Log.Info(Msg.Executing(workerMethod.Method.ToFriendlyName()), entryCategory, GetUserName());
            try
            {
                workerMethod(param);
            }
            catch (Exception e)
            {
                Log.Error(e, entryCategory, GetUserName());
            }
        }
        

        public static T FunctionTemplate<T>(Func<T> workerMethod, EntryCategories entryCategory)
        {
            if (workerMethod == null)
            {
                throw new ArgumentNullException("workerMethod");
            }
            Log.Info(Msg.Executing(workerMethod.Method.ToFriendlyName()), entryCategory, GetUserName());
            T result = default(T);
            try
            {
                result = workerMethod();
            }
            catch (Exception e)
            {
                Log.Error(e, entryCategory, GetUserName());
            }
            return result;
        }

        public static TOut FunctionTemplate<TIn, TOut>(Func<TIn, TOut> workerMethod, TIn param)
        {
            if (workerMethod == null)
            {
                throw new ArgumentNullException("workerMethod");
            }
            Log.Info(Msg.Executing(workerMethod.Method.ToFriendlyName()), EntryCategories.REST, GetUserName());
            TOut result = default(TOut);
            try
            {
                result = workerMethod(param);
                if (typeof(TOut).IsClass && result == null)
                {
                    Log.Warning(Msg.NotFound(param), EntryCategories.REST, GetUserName());
                }
                else
                {
                    Log.Info(Msg.Found(param, result), EntryCategories.REST, GetUserName());
                }
            }
            catch (Exception e)
            {
                Log.Error(e, EntryCategories.REST, GetUserName());
            }
            return result;
        }
        

        public static TOut FunctionTemplate<TIn1, TIn2, TOut>(Func<TIn1, TIn2, TOut> workerMethod, TIn1 param1, TIn2 param2)
        {
            if (workerMethod == null)
            {
                throw new ArgumentNullException("workerMethod");
            }
            Log.Info(Msg.Executing(workerMethod.Method.ToFriendlyName()), EntryCategories.REST, GetUserName());
            TOut result = default(TOut);
            try
            {
                result = workerMethod(param1, param2);
                if (typeof(TOut).IsClass && result == null)
                {
                    Log.Warning(Msg.NotFound(param1), EntryCategories.REST, GetUserName());
                }
                else
                {
                    Log.Info(Msg.Found(param1, result), EntryCategories.REST, GetUserName());
                }
            }
            catch (Exception e)
            {
                Log.Error(e, EntryCategories.REST, GetUserName());
            }
            return result;
        }
    }
}